package com.example.javaproject;

import com.example.javaproject.com.example.java.enums.TechHost;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Calendar;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MyClass {
    private static final int MIN_INITIAL_CAPACITY = 8;
    private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal() {
        @Override
        protected Object initialValue() {
            return new SimpleDateFormat();
        }
    };

    public static SimpleDateFormat getFormat(String pattern) {
        SimpleDateFormat simpleDateFormat = threadLocal.get();
        simpleDateFormat.applyPattern(pattern);
        return simpleDateFormat;
    }

    public static String getDaysOfMonth() {
        Calendar calendar = Calendar.getInstance();
        /*calendar.setTime(new Date());*/
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + "";
    }

    public static void main(String[] args) {
        System.out.println(Integer.toBinaryString(-1));
        System.out.println(Integer.toBinaryString(4));

        System.out.println(-1 & 4);

        int numElements = 9;
        System.out.println(Integer.toBinaryString(numElements));
        int initialCapacity = MIN_INITIAL_CAPACITY;
        if (numElements >= initialCapacity) {
            initialCapacity = numElements;
            initialCapacity |= (initialCapacity >>> 1);
            System.out.println("initialCapacity |= (initialCapacity >>> 1) " + initialCapacity);
            initialCapacity |= (initialCapacity >>> 2);
            System.out.println("initialCapacity |= (initialCapacity >>> 2) " + initialCapacity);
            initialCapacity |= (initialCapacity >>> 4);
            System.out.println("initialCapacity |= (initialCapacity >>> 4); " + initialCapacity);
            initialCapacity |= (initialCapacity >>> 8);
            System.out.println("initialCapacity |= (initialCapacity >>> 8) " + initialCapacity);

            initialCapacity |= (initialCapacity >>> 16);
            System.out.println("initialCapacity |= (initialCapacity >>> 16) " + initialCapacity);
            initialCapacity++;

            if (initialCapacity < 0)    // Too many elements, must back off
                initialCapacity >>>= 1; // Good luck allocating 2^30 elements

            System.out.println(" " + initialCapacity);
        }

        /*System.out.println(getDaysOfMonth());
        long t = System.currentTimeMillis();
        long t2 = t + TimeUnit.DAYS.toMillis(30);
        SimpleDateFormat simpleDateFormat = getFormat("yyyy-MM-dd");
        System.out.println(simpleDateFormat.format(new Date(t)));
        System.out.println(simpleDateFormat.format(new Date(t2)));

        System.out.println(Integer.MAX_VALUE);
        System.out.println(Math.pow(2, 31) - 1);

        System.out.println(((JOB_TYPE_USER_BEHAVIOR << 25) - 1));
        System.out.println(getJobId(JOB_TYPE_USER_BEHAVIOR, ((JOB_TYPE_USER_BEHAVIOR << 25) - 1)));

        HashSet<Integer> set = new HashSet<Integer>();
        for (int i = 0; i < 10; i++) {
            set.add(i);
        }
        System.out.println(set);*/

/*        CacheBean<ModelA> cacheBean = new CacheBean<>("S");
        cacheBean.doSomething();*/

//
//        Base64.getEncoder().encode()

//        writeObject(modelA);
//        propertiesUsage();


//        oldCode();

//        for (int i = 0; i < 200; i++) {
//            CustomizedThreadPool.getInstance().execute(new Mehod(i));
//        }
/*        System.out.println(ModelA.class.isAssignableFrom(BaseModel.class));

        System.out.println(BaseModel.class.isAssignableFrom(ModelA.class));*/


/*        CountDownLatch countDownLatch = new CountDownLatch(2);
        CustomizedThreadPool.getInstance().execute(new Mehod(1, countDownLatch));
        CustomizedThreadPool.getInstance().execute(new Mehod(2, countDownLatch));
        try {

            System.out.println("getCount "+countDownLatch.getCount());
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("execute "+System.currentTimeMillis());*/

/*        SingleThreadExecutor executorService = new SingleThreadExecutor("database#");
        for (int i = 0; i < 20; i++) {
            try {
                String result = executorService.submit(new Ridom(i)).get();
                System.out.println(Thread.currentThread().getName() + "#" + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        executorService.shutdown();*/
    }


    public static final int JOB_TYPE_CHANNEL_PROGRAMS = 1;
    public static final int JOB_TYPE_CHANNEL_METADATA = 2;
    public static final int JOB_TYPE_CHANNEL_DELETION = 3;
    public static final int JOB_TYPE_CHANNEL_LOGGER = 4;

    public static final int JOB_TYPE_USER_PREFS = 11;
    public static final int JOB_TYPE_USER_BEHAVIOR = 32;//6bit

    //16-1 for short. Adjust per your needs
    private static final int JOB_TYPE_SHIFTS = 25;

    public static int getJobId(int jobType, int objectId) {
        if (0 < objectId && objectId < ((JOB_TYPE_USER_BEHAVIOR << JOB_TYPE_SHIFTS))) {
            return (jobType << JOB_TYPE_SHIFTS) + objectId;
        } else {
            String err = String.format("objectId %s must be between %s and %s",
                    objectId, 0, ((jobType << JOB_TYPE_SHIFTS + 1) - 1));
            throw new IllegalArgumentException(err);
        }
    }

    static class Ridom implements Callable<String> {
        private int index;

        public Ridom(int index) {
            this.index = index;
        }

        @Override
        public String call() throws Exception {
            long value = (long) (Math.random() * 100);
            Thread.sleep(value);
            return Thread.currentThread().getName() + " sleep:" + value + " index=" + index;
        }
    }


    private static void writeObject(ModelA modelA) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            new ObjectOutputStream(byteArrayOutputStream).writeObject(modelA);
            System.out.println(Base64.getEncoder().encode(byteArrayOutputStream.toByteArray()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void propertiesUsage() {
        try {

            Properties properties = new Properties();
            properties.load(new FileInputStream("version.properties"));

            String versionName = properties.getProperty("versionName", "0");
            String versionCode = properties.getProperty("versionCode", "0");
            System.out.println("versionName=" + versionName + " versionCode=" + versionCode);

            FileOutputStream fileOutputStream = new FileOutputStream("version.properties");
            properties.setProperty("versionCode", String.valueOf(1 + Integer.parseInt(versionCode)));
            properties.store(fileOutputStream, "versionName:1");
            fileOutputStream.close();

//            properties.setProperty("versionCode", String.valueOf(1 + Integer.parseInt(versionCode)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    static class Mehod implements Runnable {
        public int index;
        CountDownLatch countDownLatch;

        public Mehod(int index) {
            this.index = index;
        }

        public Mehod(int index, CountDownLatch countDownLatch) {
            this.index = index;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                Thread.sleep((long) (Math.random() * 1000));
                System.out.println("thread " + index + " done " + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (countDownLatch != null) {
                countDownLatch.countDown();
            }
        }
    }


    private static void oldCode() {
        System.out.println(0x3000);
        System.out.println(TechHost.SAPI.getHost());
        System.out.println(Thread.currentThread().getId());


        ExecutorService executors = Executors.newCachedThreadPool();
        Future<Integer> submit = executors.submit(new ComputeCall<>(3, 4));


        ComputeCall<Integer> computeCall = new ComputeCall(1, 2);
        executors.submit(computeCall);

        System.out.println("done");

        for (int i = 0; i < 200; i++) {
            executors.execute(new Mehod(i));
        }
    }


}
